"""
Celery Worker 自动启动管理器
在主程序启动时自动启动Celery Worker进程
修改为守护进程模式，使其在主应用重载时不被终止
"""

import subprocess
import logging
import os
import signal

logger = logging.getLogger(__name__)

class CeleryWorkerManager:
    """
    Celery Worker 管理器 (启动器模式)
    这个管理器只负责在应用启动时尝试启动一个独立的、分离的Celery worker进程。
    它不会监控或管理这个进程的生命周期，以避免在FastAPI服务重载时杀死worker。
    """
    
    def __init__(self):
        self.pid_file = "celery_worker.pid"

    def start_worker(self, 
                    app_name: str = "app.celery_app",
                    queues: str = "jimeng_video,jimeng_image,jimeng_template",
                    concurrency: int = 1,
                    loglevel: str = "info") -> bool:
        """
        启动一个独立的Celery Worker进程，如果它尚未运行。
        """
        if self._is_worker_running():
            logger.info("Celery Worker 进程已在运行中。")
            return True
            
        try:
            cmd = [
                "celery",
                "-A", app_name,
                "worker",
                "-Q", queues,
                f"--loglevel={loglevel}",
                f"--concurrency={concurrency}",
                f"--pidfile={self.pid_file}",
                "--pool=solo"
            ]
            
            logger.info(f"启动独立的Celery Worker: {' '.join(cmd)}")
            
            # 使用 Popen 启动一个完全独立的进程
            # 在Unix-like系统上，这个新进程不会是当前进程的直接子进程，
            # 因此在父进程（uvicorn worker）退出时不会被终止。
            subprocess.Popen(cmd, preexec_fn=os.setsid if os.name != 'nt' else None)
            
            logger.info("Celery Worker 启动命令已发出。")
            return True
                
        except FileNotFoundError:
            logger.error("未找到celery命令，请确保已安装celery")
            return False
        except Exception as e:
            logger.error(f"启动Celery Worker异常: {e}")
            return False

    def stop_worker(self) -> bool:
        """
        尝试停止由这个管理器启动的Celery Worker进程。
        通过读取PID文件并发送SIGTERM信号来实现。
        """
        if not self._is_worker_running():
            logger.warning("Celery Worker 未运行或无法找到PID文件。")
            return True
        
        try:
            with open(self.pid_file, 'r') as f:
                pid = int(f.read().strip())
            
            logger.info(f"正在停止Celery Worker (PID: {pid})...")
            os.kill(pid, signal.SIGTERM)
            
            # 清理PID文件
            try:
                os.remove(self.pid_file)
            except OSError:
                pass

            logger.info("Celery Worker 停止信号已发送。")
            return True
        except (IOError, ValueError, ProcessLookupError) as e:
            logger.error(f"停止Celery Worker失败: {e}")
            # 如果PID文件存在但进程不存在，也清理掉
            if os.path.exists(self.pid_file):
                os.remove(self.pid_file)
            return False

    def _is_worker_running(self) -> bool:
        """
        通过检查PID文件和进程是否存在来判断worker是否在运行。
        """
        if not os.path.exists(self.pid_file):
            return False
        
        try:
            with open(self.pid_file, 'r') as f:
                pid = int(f.read().strip())
            
            # 检查进程是否存在 (在Unix-like系统上)
            if os.name != 'nt':
                os.kill(pid, 0)
            else:
                # 在Windows上，os.kill(pid, 0) 不可靠，需要更复杂的方法
                # 为简单起见，我们只检查PID文件
                logger.warning("在Windows上无法可靠地检查进程是否存在，仅依赖PID文件。")
                return True

        except (IOError, ValueError, ProcessLookupError):
            # PID文件无效或进程不存在
            return False
        except Exception:
            # 其他异常
            return False
            
        return True

# 全局Celery Worker管理器实例
celery_worker_manager = CeleryWorkerManager()